﻿using System;
using System.Collections.Generic;

namespace Core.MemCache
{
    public class Container : IContainer
    {
        private readonly Dictionary<Type, IContainer> dict = new();

        public int Count { get; private set; }

        public void Dispose()
        {
            Count = 0;
            foreach (var kvp in dict)
            {
                ReferencePool.Recycle(kvp.Value);
            }

            dict.Clear();
        }

        public void Add<T>(T value)
        {
            var t = typeof(T);

            if (!dict.ContainsKey(t))
            {
                dict[t] = ReferencePool.Acquire<HashSet<T>>();
            }

            if (dict[t] is not HashSet<T> container) return;

            if (container.Contains(value))
            {
                return;
            }

            container.Add(value);
            Count++;
        }

        public void Remove<T>(T value)
        {
            var t = typeof(T);

            if (!dict.TryGetValue(t, out var value1))
            {
                return;
            }

            if (value1 is not HashSet<T> container) return;

            if (!container.Contains(value))
            {
                return;
            }

            container.Remove(value);
            Count--;

            if (container.Count == 0)
            {
                ReferencePool.Recycle(container);
                dict.Remove(t);
            }
        }

        public void Set<T>(T value)
        {
            var t = typeof(T);

            if (!dict.ContainsKey(t))
            {
                dict[t] = ReferencePool.Acquire<HashSet<T>>();
            }

            if (dict[t] is not HashSet<T> container) return;

            Count -= container.Count;
            container.Set(value);
            Count++;
        }

        public T Get<T>()
        {
            var t = typeof(T);

            if (!dict.TryGetValue(t, out var value))
            {
                return default;
            }

            if (value is not HashSet<T> container)
            {
                return default;
            }

            return container.Get();
        }

        public bool Contains<T>(T value)
        {
            var t = typeof(T);

            if (!dict.TryGetValue(t, out var value1))
            {
                return false;
            }

            if (value1 is not HashSet<T> container)
            {
                return false;
            }

            return container.Contains(value);
        }

        public bool ContainsExcept<T>(T value)
        {
            var t = typeof(T);
            if (dict.Count > 1) return true;
            if (dict.Count == 0) return false;

            if (dict[t] is not HashSet<T> container)
            {
                return false;
            }

            if (container.Count > 1) return true;
            if (container.Count == 0) return false;

            return !container.Contains(value);
        }
    }
}